#ifndef __MODEL_H__
#define __MODEL_H__

#include "Common.h"
#include "Graphics/MeshManager.h"
#include "Graphics/Material.h"
#include "Graphics/Renderable.h"
#include "Utils/Array.h"

namespace RayFrame
{
  class Material;

  /// This class holds the data of vertex, texture coordinates, etc.
  class DLL_DECLARE Mesh
  {
    friend class MeshManager;
  protected:
    unsigned            m_nIndices;    ///<Count of the indices
    RefArray <Stream>   m_streams;     ///<Data of vertex and indices
    RefArray <Batch>    m_batches;     ///<Data of batches

    unsigned    m_lastVertexCount;     ///<Number of vertices
    float       *m_lastVertices;
    unsigned    *m_lastIndices;
    FormatDesc  *m_lastFormat;

    VertexFormatID  m_vertexFormat;
    VertexBufferID  m_vertexBuffer;
    IndexBufferID   m_indexBuffer;

    glm::mat4     m_world;
  public:
    StreamID  AddStream(const AttributeType type, const int nComponents, 
      unsigned nVertices, float *vertices, unsigned *indices, bool optimized);
    BatchID   AddBatch(const unsigned startIndex, const unsigned nIndices);
  
  protected:
    unsigned  assemble(const StreamID *aStreams, const unsigned nStreams, float **destVertices, unsigned **destIndices, bool separateArrays);
    void      optimizeStream(const StreamID streamID);
  
  public:
    Mesh();

    virtual void Render(double timeElapsed);

    unsigned GetVertexSize() const;
    unsigned GetComponentCount() const;
    unsigned GetComponentCount(const StreamID *cStreams, const unsigned nStreams) const;

    unsigned GetIndicesCount() const { return m_nIndices; }
    unsigned GetVerticesCount() const { return m_lastVertexCount; }
    void SetIndicesCount(const unsigned nInds){ m_nIndices = nInds; }

    void* GetVertices(){ return m_lastVertices; }
    void* GetIndices(){ return m_lastIndices; }

    static unsigned *GetArrayIndices(const unsigned nVertices);
    virtual unsigned MakeDrawable(const bool useCache = true);
  };
}

#endif
